﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Linq;
using MediaBrowserWS.Service;

namespace MediaBrowserWS.Code
{
    static class AppSettings
    {
        private enum AppSettingTypes
        {
            Port,
            ShowLoadSuccess,
            Log
        }

        public static void Initialise()
        {
            ApplicationStartTime = DateTime.Now;
            Refresh();
            Save();
        }

        public static void Refresh()
        {
            BasePort = GetSetting<int>(AppSettingTypes.Port);
            ShowLoadSuccess = GetSetting<bool>(AppSettingTypes.ShowLoadSuccess);
            Log = GetSetting<bool>(AppSettingTypes.Log);
        }

        private static void Save()
        {
            XElement parentNode = new XElement("Settings",
                new XElement(AppSettingTypes.Port.ToString(), BasePort),
                new XElement(AppSettingTypes.Log.ToString(), Log),
                new XElement(AppSettingTypes.ShowLoadSuccess.ToString(), ShowLoadSuccess));

            XDocument doc = new XDocument(parentNode);
            FileLocation.Directory.EnsureDirectoryExistance();
            doc.Save(FileLocation.FullName, SaveOptions.None);
        }

        #region Dynamic Settings

        public static bool Log { get; set; }

        public static int BasePort { get; private set; }

        public static bool ShowLoadSuccess { get; private set; }

        #endregion

        #region Constant Settings

        public static DateTime ApplicationStartTime { get; set; }

        public static FileInfo FileLocation
        {
            get
            {
                return new FileInfo(Path.Combine(AppSettings.MediaBrowserWsDirectory.FullName, @"WebServiceSettings.xml"));
            }
        }

        public static Uri Address(int port)
        {
            string url = string.Format(@"http://{0}:{1}/MediaBrowserService", System.Environment.MachineName, port);
            return new Uri(url);
        }

        private static Dictionary<string, string> _mimeTypes;
        public static Dictionary<string, string> MimeTypes
        {
            get
            {
                if (_mimeTypes == null)
                {
                    _mimeTypes = new Dictionary<string, string>();
                    _mimeTypes.Add("bmp", "image/bmp");
                    _mimeTypes.Add("css", "text/css");
                    _mimeTypes.Add("gif", "image/gif");
                    _mimeTypes.Add("htm", "text/html");
                    _mimeTypes.Add("html", "text/html");
                    _mimeTypes.Add("jpeg", "image/jpeg");
                    _mimeTypes.Add("jpg", "image/jpeg");
                    _mimeTypes.Add("js", "application/x-javascript");
                    _mimeTypes.Add("manifest", "text/cache-manifest");
                    _mimeTypes.Add("png", "image/png");
                    _mimeTypes.Add("tif", "image/tiff");
                    _mimeTypes.Add("tiff", "image/tiff");
                }
                return _mimeTypes;
            }
        }

        #endregion

        #region Private Methods

        private static T GetSetting<T>(AppSettingTypes type)
        {
            T retVal = default(T);
            bool successfulLoad = false;
            try
            {
                string value = Document.Descendants(type.ToString()).Single().Value;
                retVal = ParseValue<T>(value);
                successfulLoad = true;
            }
            catch (Exception) { }

            if (!successfulLoad)
            {
                string value = GetDefault(type);
                retVal = ParseValue<T>(value);
            }

            return retVal;
        }

        private static T ParseValue<T>(string value)
        {
            object retVal = null;
            Type type = typeof(T);
            if (type == typeof(int))
            {
                retVal = int.Parse(value);
            }
            else if (type == typeof(bool))
            {
                retVal = bool.Parse(value);
            }
            else if (type == typeof(List<string>))
            {
                string[] vals = value.Split(';');
                retVal = new List<string>(vals);
            }
            else
            {
                throw new InvalidCastException("Unable to parse as type " + type);
            }

            return (T)retVal;
        }

        private static string GetDefault(AppSettingTypes type)
        {
            string retVal = string.Empty;
            switch (type)
            {
                case AppSettingTypes.Log:
                    {
                        retVal = bool.FalseString;
                        break;
                    }
                case AppSettingTypes.Port:
                    {
                        retVal = "40600";
                        break;
                    }
                case AppSettingTypes.ShowLoadSuccess:
                    {
                        retVal = bool.FalseString;
                        break;
                    }
            }

            return retVal;
        }

        #endregion

        #region Private Members

        private static XDocument _document;
        private static XDocument Document
        {
            get
            {
                if (_document == null)
                    _document = XDocument.Load(FileLocation.FullName);
                return _document;
            }
        }

        #endregion

        public static DirectoryInfo MediaBrowserWsDirectory
        {
            get { return new DirectoryInfo(Path.Combine(ProgramDataDirectory.FullName, @"MediaBrowser\MediaBrowserWS")); }
        }

        public static DirectoryInfo WebPageBaseDirectory
        {
            get
            {
                DirectoryInfo dir = new DirectoryInfo(Path.Combine(MediaBrowserWsDirectory.FullName, "Web"));
                dir.EnsureDirectoryExistance();
                return dir;
            }
        }

        static DirectoryInfo ProgramDataDirectory
        {
            get
            {
                return new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
            }
        }

        public static DirectoryInfo TrailersCacheDirectory
        {
            get
            {
                DirectoryInfo dir = new DirectoryInfo(Path.Combine(MediaBrowserWsDirectory.FullName, "TrailersCache"));
                dir.EnsureDirectoryExistance();
                return dir;
            }
        }
    }
}
